package classifier;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import polarity.PolarityManager;

import files.Tweet;
import java.util.List;
import tools.IntComparator;
import tools.MyTreeMap;

/**
 * Classifieurs
 * @author Z
 */
public class Classifier 
{

	private TreeMap<String, HashMap<Integer, Integer>> vocabularyPositive = new TreeMap<String, HashMap<Integer, Integer>>();
	private TreeMap<String, HashMap<Integer, Integer>> vocabularyNegative = new TreeMap<String, HashMap<Integer, Integer>>();
	private TreeMap<String, HashMap<Integer, Integer>> vocabularyNeutral = new TreeMap<String, HashMap<Integer, Integer>>();
	private TreeMap<String, HashMap<Integer, Integer>> vocabularyIrrevelant = new TreeMap<String, HashMap<Integer, Integer>>();
	
	public TreeMap<String, HashMap<Integer, Integer>> getVocabularyPositive() { return vocabularyPositive; }
	public TreeMap<String, HashMap<Integer, Integer>> getVocabularyNegative() { return vocabularyNegative; }
	public TreeMap<String, HashMap<Integer, Integer>> getVocabularyNeutral() { return vocabularyNeutral; }
	public TreeMap<String, HashMap<Integer, Integer>> getVocabularyIrrevelant() { return vocabularyIrrevelant; }
	
	private TreeMap<String, Integer> vocabularyGeneral = new TreeMap<String, Integer>();
	
	public TreeMap<String, Integer> getVocabularyGeneral() { return vocabularyGeneral; }
        
     
    PolarityManager polarityManager = new PolarityManager();
    
    /*
     * Renvoie le manager de polarite
     */
    public PolarityManager getPolarityManager() { return polarityManager; }


        
        private int numberOfTweetPositive = 0;
	private int numberOfTweetNegative = 0;
	private int numberOfTweetNeutral = 0;
	private int numberOfTweetIrrevelant = 0;
        
        // pour le calcul de la moyenne de la longueur d'un tweet
        private int tweetSizeAverage = 0;
        private int numberOfTweets = 0;
	/*
	private static TreeMap<String, Integer> vocabularyPositiveWordCount = new TreeMap<String, Integer>();
	private static TreeMap<String, Integer> vocabularyNegativeWordCount = new TreeMap<String, Integer>();
	private static TreeMap<String, Integer> vocabularyNeutralWordCount = new TreeMap<String, Integer>();
	private static TreeMap<String, Integer> vocabularyIrrevelantWordCount = new TreeMap<String, Integer>();
*/
	/**
         * Renvoie le nombre de tweets
         * @param polarityName type de polarite
         * @return  nombre de tweets
         */
	public int getNumberOfTweet(String polarityName) { return polarityManager.getPolarityHt().get(polarityName).getNumberOfTweet(); }
	
	/**
         * supprime les mots rares
         */
        public void suppressRareWords()
        {
            MyTreeMap words = new MyTreeMap();
            for (Map.Entry<String, Integer> set : vocabularyGeneral.entrySet())
            {
                words.put(set.getValue(), set.getKey());
            }
            
            TreeMap<String, Integer> vocabularyWithoutRareWords = new TreeMap<String, Integer>();
            for (Map.Entry<Integer, List<String>> set : words.entrySet()){
                for(String mot : set.getValue()){
                    if(set.getKey() > 100){
                        vocabularyWithoutRareWords.put(mot, set.getKey());
                    }
                }
            }
            vocabularyGeneral = vocabularyWithoutRareWords;
        }
        
        /**
         * Retourne la taille moyenne d'un tweet
         * @return 
         */
        public int getAverageSizeOfTweets()
        {
            return tweetSizeAverage / polarityManager.getNumberOfTweet();
        }
        
        /**
         * Retourne le nombre de mots au total dans les tweets du classifieur
         * @return 
         */
        public int getNumberOfWords()
        {
            int total = 0;
            for (Map.Entry<String, Integer> set : vocabularyGeneral.entrySet())
                total += set.getValue();
            return total;
        }
        
        /**
         * Retourne le nombre de mots differents existants dans les tweets du classifieur
         * @return 
         */
        public int getNumberOfDifferentWords(){ return vocabularyGeneral.size(); }
	
        public TreeMap<String, Integer> getTwentyMostFrequentWords()
        {
            MyTreeMap words = new MyTreeMap(new IntComparator());
            for (Map.Entry<String, Integer> set : vocabularyGeneral.entrySet())
            {
                words.put(set.getValue(), set.getKey());
            }
            
            TreeMap<String, Integer> twentyWords = new TreeMap<String, Integer>();
            int i = 0;
            for (Map.Entry<Integer, List<String>> set : words.entrySet()){
                for(String mot : set.getValue()){
                    if(i < 20){
                        twentyWords.put(mot, set.getKey());
                        i++;
                    }
                }
            }
            /*HashMap<String, Integer> twentyWords = new HashMap<String, Integer>();
            for (Map.Entry<String, Integer> set : vocabularyGeneral.entrySet())
            {
                if(twentyWords.size() < 20)
                {
                    twentyWords.put(set.getKey(), set.getValue());
                    System.out.println(twentyWords.size());
                    System.out.println(twentyWords.entrySet().size());
                }
                else
                {
                    boolean ajoute = false;
                    for(Map.Entry<String, Integer> word : twentyWords.entrySet())
                    {
                        if(!ajoute && set.getValue() > word.getValue())
                        {
                            twentyWords.remove(word);
                            twentyWords.put(set.getKey(), set.getValue());
                            ajoute = true;
                        }
                    }
                }
            }*/
            return twentyWords;
        }
        
	/**
         * Rajoute un nouvel entrainement
         * @param tweetTrain 
         */
	public void addTweetTrain(Tweet tweetTrain)
	{
                //Ajout au calcul de la longueur moyenne d'un tweet
                tweetSizeAverage += tweetTrain.getTweetSize();
                numberOfTweets ++;
                
		TreeMap<String, HashMap<Integer, Integer>> vocabulary = null;
		polarityManager.incNumberOfTweet();
		// On incremente le nombre de tweet de la polarite du tweet
		polarityManager.getPolarityHt().get(tweetTrain.getType()).incNumberOfTweet();
		
		TreeMap<String, Integer> vocabularyPolarity = polarityManager.getPolarityHt().get(tweetTrain.getType()).getVocabulary();
		switch(tweetTrain.getType())
		{
			case "positive": 
			{
				vocabulary = vocabularyPositive;
				break;
			}
			case "negative": 
			{
				vocabulary = vocabularyNegative;
				break;
			}
			case "neutral":
			{
				vocabulary = vocabularyNeutral;
				break;
			}
			case "irrelevant": 
			{
				vocabulary = vocabularyIrrevelant;
				break;
			}
			default :
			{
				System.out.println("Erreur Type");
				break;
			}
		}
		
		TreeMap<String, Integer> vocabularyTweet = tweetTrain.getVocabulary();
		// Mot Occurence
		for (Map.Entry<String, Integer> set : vocabularyTweet.entrySet() ) 
		{
			// treeMap : Mot IdTweet Occurence
		
			// Si le mot est deja present dans le vocabulaire alors on le rajoute a la liste actuelle la paire idTweet - occurence du mot
			if ( vocabulary.containsKey(set.getKey()) == true)
			{
				vocabulary.get(set.getKey()).put(tweetTrain.getId(), set.getValue());
			}
			// Sinon on initialise la liste et on ajoute la paire idTweet - occurence du mot
			else
			{
				HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
				hm.put(tweetTrain.getId(), set.getValue());
				vocabulary.put(set.getKey(), hm);
			}
			
			// Si le mot est deja present dans le vocabulaire global alors on incremente son occurence
			if ( vocabularyGeneral.containsKey(set.getKey()) == true)
			{
				vocabularyGeneral.put(set.getKey(), vocabularyGeneral.get(set.getKey())+set.getValue());
			}
			// Sinon on l'initialise
			else
			{
				vocabularyGeneral.put(set.getKey(), set.getValue());
			}
			
			if ( polarityManager.getVocabulary().containsKey(set.getKey()) == true)
			{
				 polarityManager.getVocabulary().put(set.getKey(),  polarityManager.getVocabulary().get(set.getKey())+set.getValue());
			}
			else
			{
				 polarityManager.getVocabulary().put(set.getKey(), set.getValue());
			}
			
			
			if ( vocabularyPolarity.containsKey(set.getKey()) == true)
			{
				vocabularyPolarity.put(set.getKey(), vocabularyPolarity.get(set.getKey())+set.getValue());
			}
			else
			{
				vocabularyPolarity.put(set.getKey(), set.getValue());
			}
			
			
		}
		
	}

        /**
         * Affiche le vocabulaire positif
         */
	public void printVocabularyPositive()
	{
		System.out.println("Vocabulary Positive : ");
		for (Entry<String, HashMap<Integer, Integer>> set : vocabularyPositive.entrySet() ) 
		{
			String stringToPrint = "";
			stringToPrint = set.getKey()+" :(";
			for (Entry<Integer, Integer> set2 : vocabularyPositive.get(set.getKey()).entrySet() ) 
			{
				stringToPrint += "idTweet-"+set2.getKey()+" occ-"+set2.getValue()+" ,";
				//System.out.println("\t Tweet : "+set2.getKey());
				//System.out.println("\t Occurence : "+set2.getValue());
			}
			// on retire le " ,"
			stringToPrint = stringToPrint.substring(0, stringToPrint.length()-2);
			stringToPrint += ")";
			System.out.println(stringToPrint);
		}
	}
	 /**
         * Affiche le vocabulaire negatif
         */
	public void printVocabularyNegative()
	{
		for (Entry<String, HashMap<Integer, Integer>> set : vocabularyNegative.entrySet() ) 
		{
			System.out.println("Mot : "+set.getKey());
			for (Entry<Integer, Integer> set2 : vocabularyNegative.get(set.getKey()).entrySet() ) 
			{
				System.out.println("\t Tweet : "+set2.getKey());
				System.out.println("\t Occurence : "+set2.getValue());
			}
		}
	}
	
         /**
         * Affiche le vocabulaire neutre
         */
	public void printVocabularyNeutral()
	{
		for (Entry<String, HashMap<Integer, Integer>> set : vocabularyNeutral.entrySet() ) 
		{
			System.out.println("Mot : "+set.getKey());
			for (Entry<Integer, Integer> set2 : vocabularyNeutral.get(set.getKey()).entrySet() ) 
			{
				System.out.println("\t Tweet : "+set2.getKey());
				System.out.println("\t Occurence : "+set2.getValue());
			}
		}
	}
	
        /**
         * Affiche le vocabulaire non traite
         */
	public void printVocabularyIrrevelant()
	{
		/*
		for (Entry<String, HashMap<Integer, Integer>> set : vocabularyIrrevelant.entrySet() ) 
		{
			System.out.println("Mot : "+set.getKey());
			for (Entry<Integer, Integer> set2 : vocabularyIrrevelant.get(set.getKey()).entrySet() ) 
			{
				System.out.println("\t Tweet : "+set2.getKey());
				System.out.println("\t Occurence : "+set2.getValue());
			}
		}
		*/
		System.out.println("Vocabulary Irrevelant : ");
		for (Entry<String, HashMap<Integer, Integer>> set : vocabularyIrrevelant.entrySet() ) 
		{
			String stringToPrint = "";
			stringToPrint = set.getKey()+" :(";
			for (Entry<Integer, Integer> set2 : vocabularyIrrevelant.get(set.getKey()).entrySet() ) 
			{
				stringToPrint += "idTweet-"+set2.getKey()+" occ-"+set2.getValue()+" ,";
				//System.out.println("\t Tweet : "+set2.getKey());
				//System.out.println("\t Occurence : "+set2.getValue());
			}
			// on retire le " ,"
			stringToPrint = stringToPrint.substring(0, stringToPrint.length()-2);
			stringToPrint += ")";
			System.out.println(stringToPrint);
		}
	}


}
